#ifndef ACAPELLA_WORKER_TASK_BASE_HPP
#define ACAPELLA_WORKER_TASK_BASE_HPP

#include <acapella/delegate/delegate.hpp>
#include <acapella/synchronize/synchronize.h>
#include <acapella/queue/queue.h>
#include <acapella/shared_ptr.hpp>


namespace acapella
{
namespace worker
{

class TaskBase
{
public:
	virtual ~TaskBase(){};
	virtual void run() = 0;
	virtual void wait() = 0;
};


class Task : public TaskBase

{
public:
    virtual ~Task(){};
};

typedef acapella::shared_ptr<Task> TaskPtr;
typedef acapella::queue::Queue<TaskPtr> TaskQueue;
typedef acapella::shared_ptr<TaskQueue> TaskQueuePtr;


template
<
    typename delegateType, 
    typename SemaphoreType
>
class SyncTask 
	: public Task
{
private:
	typedef typename acapella::shared_ptr<delegateType> delegateTypePtr;
	typedef typename delegateType::return_type return_type;

public:
	SyncTask(delegateTypePtr pDelegate, return_type& returnRef)
		:pDelegate_(pDelegate), returnRef_(returnRef){}
	~SyncTask(){}

	void run()
	{
		returnRef_ = pDelegate_->Do();
		sem_.post();
		return;
	}

	void wait()
	{
		sem_.wait();
		return;
	}

private:
	SemaphoreType sem_;
	delegateTypePtr pDelegate_;
	return_type& returnRef_;
};

template<typename delegateType>
class AsynTask
	: public Task
{
private:
	typedef acapella::shared_ptr<delegateType> delegateTypePtr;
	typedef typename delegateType::return_type return_type;

public:
	AsynTask(delegateTypePtr pDelegate)
		:pDelegate_(pDelegate){}
	~AsynTask(){}

	void run()
	{
		pDelegate_->Do();
		return;
	}

    void wait()
    {
        return;
    }


private:
	delegateTypePtr pDelegate_;
};



}
}


#endif
